(function (angular) {
    'use strict';
    var baseModule = angular.module("fs.http");
    baseModule.provider("httpInterceptor", httpInterceptorProvider);
    baseModule.provider("httpParamSerializer", httpParamSerializerProvider);
    baseModule.provider('ajaxServiceFactory', ajaxServiceFactory);

    httpInterceptorProvider.$inject = [];
    function httpInterceptorProvider() {
        this.$get = httpInterceptor;
        httpInterceptor.$inject = ['$rootScope', 'HttpConstants', 'loggerFactory', 'storageService', '$q', '$injector'];
        function httpInterceptor($rootScope, HttpConstants, loggerFactory, storageService, $q, $injector) {
            var isExistSuffix = function (objStr) {
                var urlSuffixArray = ["uniqueCheck", "lookupCheck", "holidays"];
                for (var i = 0; i < urlSuffixArray.length; i++) {
                    if (objStr.indexOf(urlSuffixArray[i]) != -1) {
                        return true;
                        break;
                    }
                }
                return false;
            };
            var interceptor = {
                'request': function (config) {
                    var defered, log, csrfToken, transToken;
                    defered = $q.defer();
                    log = loggerFactory.getLogger('request');
                    config.headers[HttpConstants.DEF_XHRHEADERNAME] = HttpConstants.DEF_XHRHEADERVALUE;
                    if (config.url.indexOf("do/") >= 0) {
                        if (!isExistSuffix(config.url)) $injector.get('modalService').openLoading();
                        csrfToken = HttpConstants.CSRF_TOKEN ? storageService.getItemFromSession(HttpConstants.CSRF_TOKEN) : undefined;
                        transToken = HttpConstants.TRANSACTION_TOKEN ? storageService.getItemFromSession(HttpConstants.TRANSACTION_TOKEN) : undefined;
                        if (csrfToken) {
                            config.headers[HttpConstants.CSRF_TOKEN] = csrfToken;
                        }
                        if (transToken) {
                            config.headers[HttpConstants.TRANSACTION_TOKEN] = transToken;
                        }
                        if (config.data && config.data.hasOwnProperty('taskId')) {
                            config.headers['taskId'] = config.data.taskId;
                        }
                        defered.resolve(config);
						/*if (request.url.indexOf("do/p/") >= 0) {
						} else {
							requestKey = getRequestKey(request);
							if (isDuplicateRequest(requestKey)) {
								deferred.reject({
									errorCode : 'DUPLUCATE_REQUEST',
									errorMsg : "Duplicate Request: " + angular.toJson(request)
								});
							} else {
								addRequestKey(requestKey);
								deferred.resolve(request);
							}
						}*/
                    } else if (config.url.indexOf(".html") > 0) {
                        config.headers['Accept'] = 'text/html';
                        defered.resolve(config);
                    } else {
                        defered.resolve(config);
                    }
                    return defered.promise;
                },
                'response': function (response) {
                    var deferred, log, csrfToken, transToken, errorCode;
                    if (response.config.url.indexOf("do/") >= 0) {
                        if (!isExistSuffix(response.config.url)) $injector.get('modalService').closeLoading();
                    }
                    deferred = $q.defer();
                    log = loggerFactory.getLogger('response');
                    csrfToken = HttpConstants.CSRF_TOKEN ? response.headers(HttpConstants.CSRF_TOKEN) : undefined;
                    transToken = HttpConstants.TRANSACTION_TOKEN ? response.headers(HttpConstants.TRANSACTION_TOKEN) : undefined;
                    if (csrfToken) {
                        storageService.setItemToSession(HttpConstants.CSRF_TOKEN, csrfToken);
                    }
                    if (transToken) {
                        storageService.setItemToSession(HttpConstants.TRANSACTION_TOKEN, transToken);
                    }
                    if (response.status == 200) {
                        if (response.error) {
                            errorCode = response.error;
                            if (errorCode == HttpConstants.ERROR_CODE_SESSION_TIMEOUT) {
                                $rootScope.$emit(HttpConstants.NOTIFY_REDIRECT, {
                                    url: 'do/p/signon'
                                });
                                deferred.reject(response);
                            } else if (errorCode == CommonConHttpConstantsstants.ERROR_CODE_UNAUTHORIZED) {
                                $rootScope.$emit(HttpConstants.NOTIFY_UNAUTHORIZED, response.error);
                                deferred.reject(response);
                            } else if (errorCode == HttpConstants.ERROR_CODE_CUSTOMER_ERROR) {
                                $rootScope.$emit(HttpConstants.NOTIFY_CUSTOMER_ERROR, response.error);
                                deferred.reject(response);
                            } else {
                                $rootScope.$emit(HttpConstants.NOTIFY_SYSTEM_ERROR, response.error);
                                deferred.reject(response);
                            }
                        } else {
                            deferred.resolve(response);
                        }
                    }
                    return deferred.promise;
                },
                'requestError': function (rejection) {
                    var log = loggerFactory.getLogger('requestError');
                    if (rejection.config && rejection.config.url.indexOf("do/") >= 0) {
                        if (!isExistSuffix(rejection.config.url)) $injector.get('modalService').closeLoading();
                    }
                    if (rejection.config && rejection.config.url == "do/p/signonCheck") {
                        rejection.config.data = null;
                    }
                    log.debug(angular.toJson(rejection));
                    return $q.reject(rejection);
                },
                'responseError': function (rejection) {
                    var deferred = $q.defer();
                    var log = loggerFactory.getLogger('responseError'), csrfToken, transToken;
                    csrfToken = HttpConstants.CSRF_TOKEN ? rejection.headers(HttpConstants.CSRF_TOKEN) : undefined;
                    transToken = HttpConstants.TRANSACTION_TOKEN ? rejection.headers(HttpConstants.TRANSACTION_TOKEN) : undefined;
                    if (csrfToken) {
                        storageService.setItemToSession(HttpConstants.CSRF_TOKEN, csrfToken);
                    }
                    if (transToken) {
                        storageService.setItemToSession(HttpConstants.TRANSACTION_TOKEN, transToken);
                    }
                    if (rejection.config && rejection.config.url.indexOf("do/p/signonCheck") >= 0) {
                        rejection.config.data = "******";
                    }
                    log.debug(angular.toJson(rejection.data));
					/*if (angular.isObject(rejection) && rejection.errorCode == 'DUPLUCATE_REQUEST') {
						return deferred.reject(rejection.data);
					}*/
                    if (rejection.headers) {
                        csrfToken = HttpConstants.CSRF_TOKEN ? rejection.headers(HttpConstants.CSRF_TOKEN) : undefined;
                        transToken = HttpConstants.TRANSACTION_TOKEN ? rejection.headers(HttpConstants.TRANSACTION_TOKEN) : undefined;
                        if (csrfToken) {
                            storageService.setItemToSession(HttpConstants.CSRF_TOKEN, csrfToken);
                        }
                        if (transToken) {
                            storageService.setItemToSession(HttpConstants.TRANSACTION_TOKEN, transToken);
                        }
                    }
                    if (rejection.config && rejection.config.url.indexOf("do/") >= 0) {
                        if (!isExistSuffix(rejection.config.url)) $injector.get('modalService').closeLoading();
                    }
                    if (rejection.status != 404 || rejection.config.url.indexOf("/E404") < 0) {
                        $rootScope.$emit(HttpConstants.HTTP_ERROR_STATUS[rejection.status], rejection.data);
                    }
                    if (rejection.status == 401 || rejection.status == 501) {
                        deferred.reject(rejection.data);
                    }
                    return deferred.promise;
                }
            };
            return interceptor;
        }
    }

    httpParamSerializerProvider.$inject = [];
    function httpParamSerializerProvider() {
        this.$get = httpParamSerializer;
        httpParamSerializer.$inject = ['$injector', 'formatService', 'storageService'];
        function httpParamSerializer($injector, $filter) {
            return function (params) {
                if (!params)
                    return '';
                angular.forEach(params, function (value, key) {
                    if (value === null || angular.isUndefined(value))
                        return;
                    if (angular.isDate(value)) {
                        params[key] = formatService.formatDate(value, 'longTimestamp');
                    }
                });
                return $injector.get('$HttpParamSerializer')(params);
            };
        }
    }

    ajaxServiceFactory.$inject = [];
    function ajaxServiceFactory() {
        var provider = this;
        provider.baseUrl = '';
        provider.params = {};
        provider.setBaseUrl = function (url) {
            provider.baseUrl = url;
        };
        provider.setDefaultParmas = function (params) {
            provider.params = params;
        };
        provider.$get = ['$resource', '$q', '$timeout', 'loggerFactory', 'storageService', '$parse', function ($resource, $q, $timeout, loggerFactory, storageService, $parse) {
            var log = loggerFactory.getLogger('ajaxServiceFactory');
            return {
                buildAjaxService: buildAjaxService,
                setBaseUrl: provider.setBaseUrl,
                setDefaultParmas: provider.setDefaultParmas
            };

            function buildAjaxService(configs) {
                var services = {}, serviceConfig;
                angular.forEach(configs, function (config, key) {
                    if (provider.baseUrl && config.url) {
                        config.url = provider.baseUrl + config.url;
                    }
                });
                services = $resource(provider.baseUrl, provider.params, configs);
                return createProxyService(configs, services);
            }
            function createProxyService(configs, services) {
                var proxyService = {};
                angular.forEach(configs, function (config, key) {
                    proxyService[key] = function (params) {
                        var deferred = $q.defer();
                        if (params && params.$type == "SearchCriteria" && params.storageSearchCriteria === true) {
                            storageService.saveSearchCriteria(params);
                        }
                        return sendRequest(config, services[key], params);
                    };
                });
                return proxyService;
            }

            function sendRequest(config, service, params) {
                var deferred = $q.defer();
                try {
                    params = angular.copy(params);
                } catch (e) {
                    log.debug('can not copy the params:' + params);
                    deferred.reject(e);
                }
                service(params, function (response) {
                    deferred.resolve({
                        data: response ? response.data : response
                    });
                }, function (error) {
                    deferred.reject(error);
                });
                return deferred.promise;
            }

        }
        ];
    }
})(angular);